class KVue {

  constructor(options) {
    // 1、通过属性保存选项数据
    // 2、把data中的成员转化为getter和setter、注入到vue实例中。
    // 3、调用observer对象，监听数据的变化
    // 4、调用compile对象，解析指令和插值表达式。
    this.$options = options;

    this.$data = options.data;
    this.observe(this.$data);

    // 模拟一下watcher的创建过程；
    new Watcher(this, 'test', (val)=>{ // 监听
      console.log(val)
    });
    console.log(this.$data.test)  // 访问属性触发getter
    new Watcher(this.foo, 'bar', (val)=>{  // 监听
      console.log(val)
    });
    console.log(this.$data.foo.bar) // 访问属性触发getter
    
    // created执行
    if(options.created){
      options.created.call(this);
    }
  }

  observe(value) {
   if(!value || typeof value !== 'object'){
     return
   }
   // 遍历该对象
   Object.keys(value).forEach(key => {
     this.defineReactive(value, key, value[key])
     // 代理data的中属性到vue实例上
     this.proxyData(key)
   })
  }

  defineReactive(obj, key, val){
    this.observe(val);  // 解决数据嵌套：递归

    const dep = new Dep();

    Object.defineProperty(obj, key, {
     get: function() {
       /*Watcher对象存在全局的Dep.target中， 只有被target标记过的才会进行依赖收集*/
       Dep.target && dep.addDep(Dep.target)
       return val;
     },
     set: function(newVal) {
       if(val === newVal) {
         return
       }
       val = newVal;
       dep.notify();
     }
    })
  }

  proxyData(key) {
    Object.defineProperty(this, key, {
      get(){
        return this.$data[key];
      },
      set(newVal){
        this.$data[key] = newVal
      }
    })
  }
}


class Dep {
  constructor() {
   this.deps = [];
  }
   addDep(dep) {
     this.deps.push(dep)
   }

   notify() {
     this.deps.forEach(dep => {
       dep.update()
     });
   }
}

class Watcher {
  constructor(vm, key, cb) {
    this.vm = vm;
    this.key = key;
    this.cb = cb;
    // 在这里将观察者本身赋值给全局的target，只有被target标记过的才会进行依赖收集
    Dep.target = this;
    // 访问属性触发getter,添加依赖
    this.vm[this.key];
    // 依赖添加后将target设为空，依赖种植
    Dep.target = null
  }

  update() {
    // console.log('属性更新了');
    this.cb.call(this.vm, this.vm[this.key]);
  }
}

export default KVue